﻿#include "library.h"

QtRedis* Library::redis = nullptr;
Library* Library::instance = nullptr;
QMutex Library::mutex;
Library::Library() : QObject()
{
    
    //redis认证
    redis = new QtRedis("106.52.18.25",2022);
    if (!redis->openConnection())
    {
        qDebug() << "Could not connect to server...";
        throw redis;
    }
    if(!redis->auth("161100Me"))
    {
        qDebug() << "redis password error";
        throw redis;
    }
    
    //实例化下载队列
    mq = DownloadMQ::Instance();
    
}


Library *Library::getInstance()
{
    if (instance == nullptr) {
        QMutexLocker locker(&mutex);
        if (instance == nullptr) {
            instance = new Library();
        }
        locker.unlock();
    }
    return instance;
}

CFile Library::get(QString qpath)
{
    qDebug()<<"get "<<qpath;
    CFile cfile;
    auto it = file_library.find(qpath);
    if(it != file_library.end())
    {
        qDebug()<<"缓存存在，返回缓存值";
        return it.value();
    }
    //如果文件缓存没有结果
    //查询数据库
    QString localPath = redis->get(qpath.toUtf8().toBase64());
#ifdef Q_OS_WIN32  //反斜杠处理
    localPath = QDir::toNativeSeparators(localPath);
#endif
    qDebug()<<"缓存结果: "<<localPath;
    
    QFile file("."+localPath);
    if(file.open(QIODevice::ReadOnly))
    {
        qDebug()<<"直接读取数据库获取文件路径";
        QByteArray fbuffer = file.readAll();
        int size = fbuffer.size();
        file.close();//读取后就关闭了
        
        //分配内存，随后存放到缓存里
        char* data = new char[size];
        memcpy(data,fbuffer.data(),size);
        
        cfile.data = data;
        cfile.size = size;
        cfile.len = size;
        file_library[qpath] = cfile;
        return cfile;
    }else{
        qDebug()<<"文件不存在:请求下载";
        qDebug()<<file.errorString();
    }
    
    
    qDebug()<<"开始时间循环 ";
    //请求下载后开始事件循环,获取文件内容
    QEventLoop loop;
    mq->download(qpath);
    QTimer *timer = new QTimer(this);
    int count=0;
    //mutable用于修改外部值，否者一般为只读
    connect(timer,&QTimer::timeout,[&]() mutable {
        if(mq->getFile(qpath,cfile) || count >=30)
        {
            timer->stop();
            timer->deleteLater();
            loop.exit();
        }
        count++;
    });
    timer->start(5000);
    
    loop.exec();
    qDebug()<<"事件循环结束 ";
    
    return cfile;
}

CFile Library::get(QString path, int start, int end)
{
    CFile file = get(path);
    file.data = file.data+start;
    file.len = end - start;
    return file;
}
